﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.Common;
using System.Data.SqlClient;
using System.IO;
using System.Threading;

namespace DBRandomGenerator
{
    /// <summary>
    /// Tries to handle each row accordingly 
    /// </summary>
    public class Row
    {
        #region "Private Variables"

        List<Column> _TableColumns = new List<Column>(); // List of columns in EACH ROW 
        private InsertStatement _InsertStatement = new InsertStatement(); // EACH ROW in Table has Insert Statement Instance
        public String GeneratedInsertStatement { get; set; }
        #endregion

        #region "Properties"

        public String ParentTable { get; set; }      // table this Row belongs to
        public ManualResetEvent _doneEvent;
        public List<Column> TableColumns
        {
            get { return _TableColumns; }
            set { _TableColumns = value; }
        }

        public int RowIndex { get; set; }


        public Row(string TableName, List<Column> columnlist)
        {
            try
            {
                this.ParentTable = TableName;
                this.TableColumns = columnlist;
                _InsertStatement.TableName = this.ParentTable;
                PopulateColumnNames();
            }
            catch (Exception ex)
            {
                throw ex.GetBaseException();
            }
        }

        public Row(string TableName, List<Column> columnlist, ManualResetEvent doneevent)
        {
            try
            {
                this.ParentTable = TableName;
                _doneEvent = doneevent;
                this.TableColumns = columnlist;
                _InsertStatement.TableName = this.ParentTable;
                PopulateColumnNames();
            }
            catch (Exception ex)
            {
                throw ex.GetBaseException();
            }
        }

        public void GenerateInsertStatement()
        {
            GetInsertStatement();
        }


        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public string GetInsertStatement()
        {
            try
            {
                lock (_InsertStatement)
                {
                    PopulateData();
                    string InsertStatement = _InsertStatement.ToString();
                    _InsertStatement.ColumnValues = String.Empty;
                    return InsertStatement;
                }
            }
            catch (Exception ex)
            {
                throw ex.GetBaseException();
            }
        }

        private void PopulateColumnNames()
        {
            try
            {
                foreach (Column TableColumn in TableColumns)
                {
                    if (TableColumn.IncludeColumn)
                    {
                        _InsertStatement.ColumnNames = _InsertStatement.ColumnNames + TableColumn.Name;

                        _InsertStatement.ColumnNames += ",";
                    }
                }
                if (_InsertStatement.ColumnNames.EndsWith(","))
                {
                    _InsertStatement.ColumnNames = _InsertStatement.ColumnNames.Remove(_InsertStatement.ColumnNames.Length - 1, 1);
                }
            }
            catch (Exception ex)
            {
                throw ex.GetBaseException();
            }
        }

        private void PopulateData()
        {
            try
            {
                foreach (Column TableColumn in TableColumns)
                {
                    if (TableColumn.IncludeColumn)
                    {
                        if (TableColumn.ForeignKey)
                        {
                            _InsertStatement.ColumnValues = _InsertStatement.ColumnValues + GetForeignKeyValue(TableColumn);
                        }
                        else
                        {
                            _InsertStatement.ColumnValues = _InsertStatement.ColumnValues + GetRandomValue(TableColumn);
                        }
                        _InsertStatement.ColumnValues += ",";
                    }
                }
                if (_InsertStatement.ColumnValues.EndsWith(","))
                {
                    _InsertStatement.ColumnValues = _InsertStatement.ColumnValues.Remove(_InsertStatement.ColumnValues.Length - 1, 1);
                }
            }
            catch (Exception ex)
            {
                throw ex.GetBaseException();
            }
        }

        public string GetForeignKeyValue(Column TableColumn)
        {
            string ColumnValue = String.Empty;
            DCM RDGenDCM = new DCM();
            try
            {
                switch (TableColumn.DataType.ToLower())
                {
                    case "bit":
                    case "int":
                    case "bigint":
                    case "decimal":
                    case "float":
                    case "money":
                    case "numeric":
                    case "real":
                    case "smallmoney":
                    case "tinyint":
                    case "smallint":
                        ColumnValue = this.GetForeignKeyValue(TableColumn, this.ParentTable);
                        break;
                    case "datetime":
                    case "smalldatetime":
                    case "char":
                    case "varchar":
                    case "nchar":
                    case "nvarchar":
                    case "text":
                    case "ntext":
                    case "uniqueidentifier":
                        ColumnValue = "'" + this.GetForeignKeyValue(TableColumn, this.ParentTable) + "'";
                        break;
                }
            }
            catch (Exception ex)
            {
                throw ex.GetBaseException();
            }
            finally
            {
                RDGenDCM = null;
            }
            return ColumnValue;
        }

        public string GetRandomValue(Column TableColumn)
        {
            string ColumnValue = String.Empty;
            try
            {
                switch (TableColumn.DataType.ToLower())
                {
                    case "uniqueidentifier":
                        ColumnValue = "'" + DataBuilder.GetUniqueIdentifier(TableColumn) + "'";
                        break;
                    case "sqlvariant":
                        ColumnValue = "'" + DataBuilder.GetSqlVariant(TableColumn) + "'";
                        break;
                    case "bit":
                        ColumnValue = DataBuilder.GetBit();
                        break;
                    case "int":
                        if (TableColumn.Name.Contains("id"))
                            ColumnValue = DataBuilder.GetID(TableColumn);
                        else
                            ColumnValue = DataBuilder.GetInt(TableColumn);
                        break;
                    case "bigint":
                    case "decimal":
                    case "float":
                    case "money":
                    case "numeric":
                    case "real":
                    case "smallmoney":

                        ColumnValue = DataBuilder.GetBigInt(TableColumn);
                        break;
                    case "datetime":
                    case "smalldatetime":
                        ColumnValue = "'" + DataBuilder.GetDateTime() + "'";
                        break;

                    case "nchar":
                    case "char":
                        ColumnValue = "'" + DataBuilder.GetChar(TableColumn) + "'";
                        break;
                    case "varchar":
                    case "nvarchar":
                        ColumnValue = "'" + DataBuilder.GetText(TableColumn) + "'";
                        break;

                    case "binary":
                    case "varbinary":
                        ColumnValue = "'" + DataBuilder.GetBinary(TableColumn) + "'";
                        break;
                    case "tinyint":
                        ColumnValue = DataBuilder.GetTinyInt();
                        break;
                    case "smallint":
                        ColumnValue = DataBuilder.GetSmallInt(TableColumn);
                        break;
                    case "text":
                    case "ntext":
                        ColumnValue = "'" + DataBuilder.GetText(TableColumn) + "'";
                        break;

                }
                return ColumnValue;
            }
            catch (Exception ex)
            {
                throw ex.GetBaseException();
            }

        }

        public string GetForeignKeyValue(Column TableColumn, string TableName)
        {
            String column = String.Empty;
            try
            {
                column = GetForeignKeyFromDB(TableColumn, TableName);
                // modified this piece to include IF statement with majority of the changes in the ELSE portion
                if (String.IsNullOrEmpty(column))
                {
                    InsertNewForeignKeyRow(TableColumn);
                }
            }
            catch (Exception ex)
            {
                throw ex.GetBaseException();
            }
            return column;
        }

        private static String GetForeignKeyFromDB(Column TableColumn, string TableName)
        {
            string ColumnValue = String.Empty;
            SqlDataReader reader =null;
            //QUERY AND GET THE RETURNED IDATAREADER OBJECT 
            DCM gen = new DCM();
            try
            {
                 reader = (SqlDataReader) gen.GetForeignKeyValue(TableColumn, TableName);
                if (reader.HasRows)
                {
                    foreach (DbDataRecord RDGenRecord in reader)
                    {
                        ColumnValue = RDGenRecord[0].ToString();
                        break;
                    }
                }
            }
            catch (Exception ex)
            {
                throw ex.GetBaseException();
            }
            finally
            {
                gen = null;
                if(reader !=null)
                reader = null;
            }
            return ColumnValue;
        }

        /// <summary>
        /// create insert  scripts for at least 5 rows into the table in question, and then call this method again to retrieve the foreignkey value
        /// </summary>
        /// <param name="TableColumn"></param>
        private static void InsertNewForeignKeyRow(Column TableColumn)
        {
            try
            {
                int iRequiredRows = 5;
                RDGenTable RDGenSelectedTable = new RDGenTable(TableColumn.ParentKeyTable.ToString());
                RDGenSelectedTable.GenerateInsertStatements(iRequiredRows);
            }
            catch (Exception ex)
            {
                throw ex.GetBaseException();
            }
        }

        #endregion
    }
}
